import * as THREE from "three";
import { Tshare } from "../utils/Tshare";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";

let container = document.querySelector("#app"),
  T = new Tshare(),
  raycaster = new THREE.Raycaster(),
  gltfLoader = new GLTFLoader().setPath("./model/"),
  chair = null,
  mesh = null,
  isTime = false,
  uniform = {
    time: { value: Date.now() },
  };

const v_s = `
varying vec3 v_position;
void main() {
  v_position = position;
  gl_Position = projectionMatrix * modelViewMatrix * vec4(v_position,1.0);
}
`;
const f_s = `
varying vec3 v_position;
uniform float time;
void main() {
  float c_y = v_position.y *abs(time) / 35.0 ;
  gl_FragColor = vec4(0.1,c_y,c_y,1.0);
}
`;

init();
animate();

function init() {
  T.initEnv(container)
    .initOrbitControls()
    // .loadHdrToScene()
    .addStats()
    .addGui("程序控制器");
  // T.scene.background.setStyle("#e3cf9a");
  T.scene.fog = new THREE.Fog(0xe3cf9a, 0, 30);
  T.camera.position.y += 2;
  T.camera.position.x -= 2;
  T.camera.position.z += 2;
  T.camera.lookAt(T.scene.position);
  T.renderer.shadowMap.enabled = true;
  T.renderer.physicallyCorrentLight = true;
  T.controls.enableDamping = true;
  T.controls.dampingFactor = 0.05;
  T.controls.maxDistance = 10;
  T.controls.minDistance = 3;
  addGUI();
  loadFBXModel("yz0.glb");
  // addGround();
  // initLight();
  container.addEventListener("click", raycasterFromScene, false);
}
function animate() {
  requestAnimationFrame(animate);
  T.renderer.render(T.scene, T.camera);
  T.stats.update();
  T.controls.update();
  if (isTime) {
    uniform.time.value = Math.sin(Date.now() * 0.001);
  }
}
async function loadFBXModel(url) {
  let { scene } = await gltfLoader.loadAsync(url);
  let cat = await gltfLoader.loadAsync("cat.glb");
  cat.scene.scale.multiplyScalar(0.035);
  cat.scene.position.y += 0.4;
  cat.scene.position.z += 0.25;
  chair = scene;
  chair.scale.multiplyScalar(1.8);
  chair.position.y -= 0.3;
  chair.traverse((mesh) => {
    if (mesh.isMesh) {
      mesh.castShadow = true;
      mesh.receiveShadow = true;
      let uniforms = {
        rimColor: { value: new THREE.Color(0x04A1FF) },
        rimPower: { value: 0.8 },
      }
      mesh.material.onBeforeCompile = function (shader) {
        shader.uniforms.rimColor = uniforms.rimColor;
        shader.uniforms.rimPower = uniforms.rimPower;

        shader.fragmentShader = /* glsl */`
                    uniform vec3 rimColor;
                    uniform float rimPower;
                        ${shader.fragmentShader.replace(
          '#include <dithering_fragment>',
          '#include <dithering_fragment>\n\tfloat dotNV = 1.0-saturate( dot( normal, geometry.viewDir ) );\n\tgl_FragColor.rgb += rimPower*dotNV*rimColor;'
        )}
                `;
      };
    }
  });
  cat.scene.traverse((mesh) => {
    if (mesh.isMesh) {
      mesh.castShadow = true;
      mesh.receiveShadow = true;
      mesh.material = new THREE.ShaderMaterial({
        vertexShader: v_s,
        fragmentShader: f_s,
        uniforms: uniform,
      });
      console.log(mesh.material);
    }
  });
  T.sceneGraph.add(chair);
}
function addGround() {
  let ground = new THREE.Mesh(
    new THREE.PlaneGeometry(100, 100),
    new THREE.MeshStandardMaterial({
      color: 0xe3cf9a,
      transparent: true,
      opacity: 0.5,
    })
  );
  ground.rotateX(-Math.PI / 2).position.y -= 1;
  ground.receiveShadow = true;
  T.scene.add(ground);
}
function initLight() {
  let dir_light = new THREE.DirectionalLight(0xffffff, 1);
  dir_light.position.set(-50, 100, -10);
  dir_light.castShadow = true;
  dir_light.shadow.blurSamples = 100;
  let point_light = new THREE.PointLight(0xffffff, 1);
  point_light.position.set(0, 5, 0);
  // T.scene.add(dir_light);
}
function raycasterFromScene(e) {
  let mouse = new THREE.Vector2(
    ((e.clientX - container.getBoundingClientRect().left) /
      container.clientWidth) *
      2 -
      1,
    -(
      (e.clientY - container.getBoundingClientRect().top) /
      container.clientHeight
    ) *
      2 +
      1
  );
  raycaster.setFromCamera(mouse, T.camera);
  let intersects = raycaster.intersectObjects(T.sceneGraph.children);
  if (intersects.length > 0) {
    console.log(intersects[0].object);
    mesh = intersects[0].object;
  }
}
function addGUI() {
  let config = {
    color: "",
    isRotate: false,
    metalness: 0,
    roughness: 0,
    opacity: 0,
    isTime: false,
  };
  T.gui
    .addColor(config, "color")
    .name("颜色")
    .onChange((c) => {
      if (mesh && !mesh.material.isArray) {
        mesh.material.color.setStyle(c);
      }
    });
  T.gui
    .add(config, "isRotate")
    .name("旋转")
    .onChange((marker) => {
      T.controls.autoRotate = marker;
    });
  T.gui
    .add(config, "metalness", 0, 1)
    .name("金属度")
    .onChange((num) => {
      if (mesh && mesh.material) {
        mesh.material.metalness = num;
      }
    });
  T.gui
    .add(config, "roughness", 0, 1)
    .name("粗糙度")
    .onChange((num) => {
      if (mesh && mesh.material) {
        mesh.material.roughness = num;
      }
    });
  T.gui
    .add(config, "opacity", 0, 1)
    .name("透明度")
    .onChange((num) => {
      if (mesh && mesh.material) {
        mesh.material.transparent ? "" : (mesh.material.transparent = true);
        mesh.material.opacity = num;
      }
    });
  T.gui
    .add(config, "isTime")
    .name("开启shader")
    .onChange((bool) => {
      isTime = bool;
    });
}
